home *** CD-ROM | disk | FTP | other *** search
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/Xatom.h>
- #include <X11/Xmu/Atoms.h>
- #include "SignalP.h"
-
- static XtResource resources[] = {
- #define offset(field) XtOffset(SignalWidget, signal.field)
- /* {name, class, type, size, offset, default_type, default_addr}, */
- { XtNtimeScale, XtCTimeScale, XtRInt, sizeof(int), offset(time_scale), XtRImmediate, (XtPointer)3},
- { XtNsampleLength, XtCSampleLength, XtRInt, sizeof(int), offset(sample_length), XtRImmediate, 0},
- { XtNsample, XtCSample, XtRInt, sizeof(int *), offset(sample), XtRImmediate, NULL},
- { XtNlevels, XtCLevels, XtRInt, sizeof(int *), offset(levels), XtRImmediate, 0},
- { XtNorigin, XtCOrigin, XtRInt, sizeof(int *), offset(origin), XtRImmediate, 0},
- { XtNinternalHeight, XtCInternalHeight, XtRInt, sizeof(int), offset(internal_height), XtRImmediate, (XtPointer)4},
- { XtNmaxSampleLength, XtCSampleLength, XtRInt, sizeof(int), offset(max_sample_length), XtRImmediate, 0},
- { XtNeditable, XtCEditable, XtRBoolean, sizeof(Boolean), offset(editable), XtRImmediate, (XtPointer)True },
- { XtNeditCallback, XtCEditCallback, XtRCallback, sizeof(XtCallbackList), offset(edit_callback), XtRImmediate, NULL},
- { XtNtimeDivision, XtCTimeDivision, XtRInt, sizeof(int), offset(time_division), XtRImmediate, 0},
- { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- offset(foreground), XtRString, "XtDefaultForeground"},
- #undef offset
- };
-
- static char translations[] = "Shift<Btn1Down>: raise()\n\
- Shift<Btn2Down>: extend()\n\
- Shift<Btn3Down>: lower()\n\
- <Key>Delete: delete-selection()\n\
- !<Btn1Down>: select-start()\n\
- !<Btn1Motion>: extend-adjust()\n\
- !<Btn1Up>: extend-end()\n\
- !<Btn2Down>: insert-selection()\n\
- !<Btn3Down>: extend-start()\n\
- !<Btn3Motion>: extend-adjust()\n\
- !<Btn3Up>: extend-end()";
-
- static void raise();
- static void lower();
- static void extend();
- static void select_start();
- static void extend_start();
- static void extend_end();
- static void extend_adjust();
- static void insert_selection();
- static void delete_selection();
-
- static XtActionsRec actions[] = {
- { "raise", raise },
- { "lower", lower },
- { "extend", extend },
- { "select-start", select_start },
- { "extend-start", extend_start },
- { "extend-end", extend_end },
- { "extend-adjust", extend_adjust },
- { "insert-selection", insert_selection },
- { "delete-selection", delete_selection },
- };
-
- static void Initialize();
- static void Destroy();
- static Boolean SetValues();
- static void Redisplay();
- static void Resize();
-
- SignalClassRec signalClassRec = {
- { /* core fields */
- /* superclass */ (WidgetClass) &simpleClassRec,
- /* class_name */ "Signal",
- /* widget_size */ sizeof(SignalRec),
- /* class_initialize */ NULL,
- /* class_part_initialize */ NULL,
- /* class_inited */ FALSE,
- /* initialize */ Initialize,
- /* initialize_hook */ NULL,
- /* realize */ XtInheritRealize,
- /* actions */ actions,
- /* num_actions */ XtNumber(actions),
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
- /* compress_enterleave */ TRUE,
- /* visible_interest */ TRUE,
- /* destroy */ Destroy,
- /* resize */ Resize,
- /* expose */ Redisplay,
- /* set_values */ SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_private */ NULL,
- /* tm_table */ translations,
- /* query_geometry */ XtInheritQueryGeometry,
- /* display_accelerator */ XtInheritDisplayAccelerator,
- /* extension */ NULL
- },
- { /* Fields for simple */
- /* change_sensitive */ XtInheritChangeSensitive
- },
- { /* signal fields */
- /* empty */ 0
- }
- };
-
- WidgetClass signalWidgetClass = (WidgetClass)&signalClassRec;
-
- static XPoint point(w,x,y)
- SignalWidget w;
- short x;
- short y;
- {
- XPoint pt;
- pt.x = x;
- pt.y = w->core.height - (w->signal.internal_height+y*w->signal.spacing);
- return(pt);
- }
-
- static void
- PrepareData(w, sample, nsample, points, npoints, scale)
- SignalWidget w;
- int sample[];
- int nsample;
- XPoint **points;
- int *npoints;
- int scale;
- {
- int x = 0, j = 0, i;
- int current;
- XPoint *p ;
-
- /* Free points and make npoint = 0 so this routine is correct even if no points are given */
-
- XtFree(*points);
- *npoints = 0;
- if(nsample==0)return;
- p = (XPoint *)XtMalloc(2*nsample*sizeof(XPoint));
- current = sample[0];
- p[j++] = point(w, x, current);
- for(i=1;i<nsample;i++){
- x+=scale;
- if(sample[i]!=current){
- p[j++] = point(w,x,current);
- p[j++] = point(w,x,current=sample[i]);
- }
- }
- x+=scale;
- p[j++] = point(w,x,current);
- p = (XPoint *)XtRealloc(p,j*sizeof(XPoint));
- for(i=j-1;i>0;i--){
- p[i].x = p[i].x - p[i-1].x;
- p[i].y = p[i].y - p[i-1].y;
- }
- *points = p;
- *npoints = j;
- }
-
- static void
- CheckLevels(sample, n, levels)
- int sample[];
- int n;
- int *levels;
- {
- int i;
- if(*levels!=0)return;
- for(i=0;i<n;i++)if(sample[i]>*levels)*levels=sample[i];
- (*levels)++;
- /* Check that level is never equal to 1 */
- if(*levels<2)*levels=2;
- }
-
- static void Recompute(w)
- SignalWidget w;
- {
- CheckLevels(w->signal.sample, w->signal.sample_length, &(w->signal.levels));
- w->signal.spacing = (w->core.height-2*w->signal.internal_height-1)/(w->signal.levels-1);
- PrepareData(w, w->signal.sample, w->signal.sample_length,
- &(w->signal.points), &(w->signal.npoints), w->signal.time_scale);
- }
-
- static void Initialize(request, new)
- SignalWidget request, new;
- {
- XGCValues values;
- values.foreground = new->signal.foreground;
- values.background = new->core.background_pixel;
- new->signal.gc = XtGetGC(new, GCForeground | GCBackground, &values);
- values.line_style = LineOnOffDash;
- values.dashes = (char) 1;
- new->signal.gc_div = XtGetGC(new, GCForeground | GCLineStyle | GCDashList , &values);
- values.foreground = new->signal.foreground ^ new->core.background_pixel;
- values.function = GXxor;
- new->signal.xor_gc = XtGetGC(new, GCForeground | GCFunction, &values);
- new->signal.points = NULL;
- new->signal.npoints = 0;
- if(new->core.height==0)new->core.height =30;
- new->signal.sample = (int *)XtMalloc(new->signal.sample_length*sizeof(int));
- bcopy(request->signal.sample, new->signal.sample, new->signal.sample_length*sizeof(int));
- Recompute(new);
- if(new->core.width==0){
- if(new->signal.npoints > 0 && new->signal.points[new->signal.npoints-1].x > 0){
- new->core.width = new->signal.points[new->signal.npoints-1].x+1;
- } else {
- new->core.width =10;
- }
- }
- }
-
- static void Destroy(w)
- SignalWidget w;
- {
- XtReleaseGC(w, w->signal.gc);
- XtReleaseGC(w, w->signal.gc_div);
- XtReleaseGC(w, w->signal.xor_gc);
- }
-
- static Boolean SetValues(old, request, new)
- SignalWidget old, request, new;
- {
- if(old->signal.sample != new->signal.sample){
- int size = new->signal.sample_length*sizeof(int);
- new->signal.sample = (int *)XtMalloc(size);
- XtFree(old->signal.sample);
- bcopy(request->signal.sample,new->signal.sample,size);
- }
- Recompute(new);
- return(True);
- }
-
- static void HighLight(w, from, to)
- SignalWidget w;
- int from, to;
- {
- int From, To;
- if(from==to)return;
-
- From = (from - w->signal.origin) * w->signal.time_scale;
- To = (to - w->signal.origin) * w->signal.time_scale;
- if(To > From){
- XFillRectangle(XtDisplay(w), XtWindow(w), w->signal.xor_gc,
- From, 0, To-From, w->core.height);
- } else {
- XFillRectangle(XtDisplay(w), XtWindow(w), w->signal.xor_gc,
- To, 0, From-To, w->core.height);
- }
- }
-
- static void Redisplay(w)
- SignalWidget w;
- {
- if(w->core.visible){
- XClearWindow(XtDisplay(w), XtWindow(w));
- if(w->signal.time_division>0){
- int x = w->signal.origin % w->signal.time_division;
- int first=(w->signal.time_division-x)*w->signal.time_scale;
- for(;
- first<w->core.width;
- first += w->signal.time_division*w->signal.time_scale)
- XDrawLine(XtDisplay(w),XtWindow(w),w->signal.gc_div,first,0,first,w->core.height);
- }
- w->signal.points[0].x = - w->signal.origin * w->signal.time_scale;
- XDrawLines(XtDisplay(w),XtWindow(w),w->signal.gc,w->signal.points,w->signal.npoints, CoordModePrevious);
- HighLight(w, w->signal.sel_start, w->signal.sel_end);
- }
- }
-
- static void Resize(w)
- SignalWidget w;
- {
- Recompute(w);
- }
-
- static int pick_unchecked(w, x)
- SignalWidget w;
- int x;
- {
- return (x/w->signal.time_scale+w->signal.origin);
- }
-
- static int pick(w, x)
- SignalWidget w;
- int x;
- {
- int victim = pick_unchecked(w, x);
- if(victim > w->signal.sample_length)victim=w->signal.sample_length;
- return(victim);
- }
-
- static void Edited(w)
- Widget w;
- {
- Recompute(w);
- XClearArea(XtDisplay(w), XtWindow(w),0,0,0,0,True);
- XtCallCallbacks(w, XtNeditCallback, NULL);
- }
-
- static void raise(w, event)
- SignalWidget w;
- XButtonPressedEvent *event;
- {
- int victim = pick(w,event->x);
- if(w->signal.editable && victim >= 0 && victim < w->signal.sample_length &&
- w->signal.sample[victim]<(w->signal.levels-1)){
- w->signal.sample[victim]++;
- Edited(w);
- }
- }
-
- static void lower(w, event)
- SignalWidget w;
- XButtonPressedEvent *event;
- {
- int victim = pick(w,event->x);
- if(w->signal.editable && victim >= 0 && victim < w->signal.sample_length &&
- w->signal.sample[victim]>0){
- w->signal.sample[victim]--;
- Edited(w);
- }
- }
-
- static void extend(w, event)
- SignalWidget w;
- XButtonPressedEvent *event;
- {
- int victim = pick_unchecked(w,event->x);
- int i;
-
- if(w->signal.editable && victim > w->signal.sample_length){
- w->signal.sample = (int *)XtRealloc((char *)w->signal.sample, victim * sizeof(int));
- for(i=w->signal.sample_length-1;i<victim;i++){
- w->signal.sample[i] = w->signal.sample[w->signal.sample_length-1];
- }
- w->signal.sample_length = victim;
- Edited(w);
- }
- }
-
- static void select_start(w, event)
- SignalWidget w;
- XButtonEvent *event;
- {
- HighLight(w, w->signal.sel_start,w->signal.sel_end);
- w->signal.sel_start = w->signal.sel_end = pick(w,event->x);
- }
- static void extend_start(w, event)
- SignalWidget w;
- XButtonEvent *event;
- {
- int victim = pick(w,event->x);
- if(abs(victim - w->signal.sel_end)>abs(victim - w->signal.sel_start)){
- int t = w->signal.sel_end;
- w->signal.sel_end = w->signal.sel_start;
- w->signal.sel_start = t;
- }
- HighLight(w, victim, w->signal.sel_end);
- w->signal.sel_end = victim;
- }
- static void canonize(from,to)
- int *from, *to;
- {
- if(*from>*to){
- int t = *to;
- *to = *from;
- *from =t;
- }
- }
- #define XA_SAMPLING(d) XmuInternAtom(d,XmuMakeAtom("SAMPLING"))
- static Boolean
- convert_selection(w, selection, target, type_return, value_return,
- length_return, format_return)
- SignalWidget w;
- Atom *selection;
- Atom *target;
- Atom *type_return;
- XtPointer *value_return;
- unsigned long *length_return;
- int *format_return;
- {
- if(*selection != XA_PRIMARY){
- XtWarning("Not selection owner!");
- return(False);
- }
- if(*target == XA_TARGETS(XtDisplay(w))){
- Atom *targets = (Atom *)XtMalloc(sizeof(Atom));
- *targets = XA_SAMPLING(XtDisplay(w));
- *value_return = (XtPointer) targets;
- *length_return = 1;
- return(True);
- }
- if(*target == XA_SAMPLING(XtDisplay(w))){
- int size = abs(w->signal.sel_start-w->signal.sel_end);
- char *new = (char *)XtMalloc(size*sizeof(int));
- canonize(&(w->signal.sel_start),&(w->signal.sel_end));
- bcopy(&(w->signal.sample[w->signal.sel_start]), new, size*sizeof(int));
- *type_return = XA_SAMPLING(XtDisplay(w));
- *value_return = new;
- *length_return = size;
- *format_return = 8*sizeof(int);
- return(True);
- }
- return(False);
- }
- static void
- receive_selection(w, client_data, sel, type, value, length, format)
- SignalWidget w;
- XtPointer client_data;
- Atom *sel, *type;
- XtPointer value;
- unsigned long *length;
- int *format;
- {
- if(*length>0){
- int *newsample = (int *)XtMalloc((w->signal.sample_length+*length)*sizeof(int));
- bcopy(w->signal.sample,newsample,(w->signal.sel_start)*sizeof(int));
- bcopy(value,&(newsample[w->signal.sel_start]),(*length)*sizeof(int));
- bcopy(&(w->signal.sample[w->signal.sel_start]),&(newsample[w->signal.sel_start+*length]),(w->signal.sample_length-w->signal.sel_start)*sizeof(int));
- XtFree(w->signal.sample);
- XtFree(value);
- w->signal.sample = newsample;
- w->signal.sample_length += *length;
- Edited(w);
- }
- }
-
- static void delete_selection(w, event)
- SignalWidget w;
- XEvent *event;
- {
- canonize(&(w->signal.sel_start),&(w->signal.sel_end));
- if(w->signal.editable && w->signal.sel_start!=w->signal.sel_end){
- int new_length = w->signal.sample_length-(w->signal.sel_end-w->signal.sel_start);
- int *newsample = (int *)XtMalloc(new_length*sizeof(int));
- bcopy(w->signal.sample,newsample,w->signal.sel_start*sizeof(int));
- bcopy(&(w->signal.sample[w->signal.sel_end]),&(newsample[w->signal.sel_start]),(w->signal.sample_length-w->signal.sel_end)*sizeof(int));
- XtFree(w->signal.sample);
- w->signal.sample = newsample;
- w->signal.sample_length = new_length;
- XtDisownSelection(w, XA_PRIMARY, CurrentTime);
- w->signal.sel_end = w->signal.sel_start;
- Edited(w);
- }
- }
-
- static void insert_selection(w, event)
- SignalWidget w;
- XButtonEvent *event;
- {
- if(w->signal.editable)
- XtGetSelectionValue(w, XA_PRIMARY, XA_SAMPLING(XtDisplay(w)),
- receive_selection, NULL, event->time);
- }
-
- static void
- lose_selection(w)
- SignalWidget w;
- {
- HighLight(w, w->signal.sel_start,w->signal.sel_end);
- w->signal.sel_end = w->signal.sel_start;
- }
- static void extend_end(w, event)
- SignalWidget w;
- XButtonEvent *event;
- {
- int victim = pick(w,event->x);
- HighLight(w, victim, w->signal.sel_end);
- w->signal.sel_end = victim;
- if(!XtOwnSelection(w, XA_PRIMARY, event->time, convert_selection, lose_selection, NULL)){
- HighLight(w, w->signal.sel_start,w->signal.sel_end);
- w->signal.sel_end = w->signal.sel_start;
- }
- }
- static void extend_adjust(w, event)
- SignalWidget w;
- XButtonEvent *event;
- {
- int victim = pick(w,event->x);
- HighLight(w, victim, w->signal.sel_end);
- w->signal.sel_end = victim;
- }
-